﻿Ext.util.Observable = Ext.extend(Object, {


    isObservable: true,

    //构造函数
    constructor: function (config) {
        var me = this;

        Ext.apply(me, config);
        if (me.listeners) {
            me.on(me.listeners);
            delete me.listeners;
        }
        //events的属性名是事件名，属性值是一个Ext.util.Event对象，它是在调用addListener为对象添加事件处理程序的时候增加元素的
        me.events = me.events || {}; 

        // 定义冒泡的事件
        if (this.bubbleEvents) {
            this.enableBubble(this.bubbleEvents);
        }
    },


    eventOptionsRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|element|vertical|horizontal)$/,

    //向任何观察的对象（或元素）添加listeners,对象（或元素）将在此组件被销毁是自动移除
    //item：Observable|Element,被添加listener/listeners的元素
    //ename：Object|String,事件名称，或一个包含事件名称属性的对象
    //fn：事件处理函数
    //scope：作用域
    //options：addListener选项
    addManagedListener: function (item, ename, fn, scope, options) {
        var me = this,
            //包含事件信息的数组，数组中每个元素都包含了Element对象、事件名、监听函数、作用域、配置信息的数组
            managedListeners = me.managedListeners = me.managedListeners || [],
            config;

        if (Ext.isObject(ename)) {//如果ename是一个对象
            options = ename;
            for (ename in options) {
                if (!options.hasOwnProperty(ename)) {//如果ename不是options的属性，则跳出继续下一个循环
                    continue;
                }
                config = options[ename];
                if (!me.eventOptionsRe.test(ename)) {//如果不符合正则表达式指定的模式
                    me.addManagedListener(item, ename, config.fn || config, config.scope || options.scope, config.fn ? config : options);
                }
            }
        }
        else {//如果ename是一个事件名称
            managedListeners.push({
                item: item,
                ename: ename,
                fn: fn,
                scope: scope,
                options: options
            });

            item.on(ename, fn, scope, options);//注册事件监听函数
        }
    },

    //移除通过addManagedListener方法添加的listeners
    removeManagedListener: function (item, ename, fn, scope) {
        var me = this,
            o,
            config,
            managedListeners,
            managedListener,
            length,
            i;

        if (Ext.isObject(ename)) {
            o = ename;
            for (ename in o) {
                if (!o.hasOwnProperty(ename)) {
                    continue;
                }
                config = o[ename];
                if (!me.eventOptionsRe.test(ename)) {
                    me.removeManagedListener(item, ename, config.fn || config, config.scope || o.scope);
                }
            }
        }

        managedListeners = this.managedListeners ? this.managedListeners.slice() : [];
        length = managedListeners.length;

        for (i = 0; i < length; i++) {
            managedListener = managedListeners[i];
            if (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope)) {
                this.managedListeners.remove(managedListener);//从managedListeners中移除元素
                item.un(managedListener.ename, managedListener.fn, managedListener.scope);//移除元素中Element的监听函数
            }
        }
    },

    //触发事件名指定的事件，传递的参数在事件名之后
    //参数：eventName事件名，args事件参数
    fireEvent: function () {
        var me = this,
            a = Ext.toArray(arguments),
            ename = a[0].toLowerCase(),//提取事件名
            ret = true,
            ev = me.events[ename],
            queue = me.eventQueue,
            parent;

        if (me.eventsSuspended === true) {//支持组件的事件挂起
            if (queue) {
                queue.push(a);
            }
            return false;
        }
        else if (ev && Ext.isObject(ev) && ev.bubble) {//指定的元素是否能进行冒泡处理
            if (ev.fire.apply(ev, a.slice(1)) === false) {
                return false;
            }
            parent = me.getBubbleTarget && me.getBubbleTarget();//进行冒泡的元素
            if (parent && parent.isObservable) {
                if (!parent.events[ename] || !Ext.isObject(parent.events[ename]) || !parent.events[ename].bubble) {
                    parent.enableBubble(ename);
                }
                return parent.fireEvent.apply(parent, a);
            }
        }
        else if (ev && Ext.isObject(ev)) {
            a.shift();
            ret = ev.fire.apply(ev, a);
        }
        return ret;
    },

    //为对象添加事件处理程序
    //ename：事件名。也可能是一个对象，它的属性名是事件名称
    //fn：事件调用的方法
    //scope：作用域，可选
    //o：事件对象，可选
    addListener: function (ename, fn, scope, o) {
        var me = this,
            config,
            ev;

        if (Ext.isObject(ename)) {
            o = ename;
            for (ename in o) {
                if (!o.hasOwnProperty(ename)) {
                    continue;
                }
                config = o[ename];
                if (!me.eventOptionsRe.test(ename)) {
                    me.addListener(ename, config.fn || config, config.scope || o.scope, config.fn ? config : o);
                }
            }
        }
        else {
            ename = ename.toLowerCase();
            me.events[ename] = me.events[ename] || true;
            ev = me.events[ename] || true;
            if (Ext.isBoolean(ev)) {
                me.events[ename] = ev = new Ext.util.Event(me, ename);//me是Event对象默认作用域，ename是事件名
            }
            ev.addListener(fn, scope, Ext.isObject(o) ? o : {});//在Event对象中存放监听函数
        }
    },

    //移除事件处理程序
    removeListener: function (ename, fn, scope) {
        var me = this,
            config,
            ev;

        if (Ext.isObject(ename)) {
            var o = ename;
            for (ename in o) {
                if (!o.hasOwnProperty(ename)) {
                    continue;
                }
                config = o[ename];
                if (!me.eventOptionsRe.test(ename)) {
                    me.removeListener(ename, config.fn || config, config.scope || o.scope);
                }
            }
        }
        else {
            ename = ename.toLowerCase();
            ev = me.events[ename]; //Ext.util.Event对象
            if (ev.isEvent) {
                ev.removeListener(fn, scope); //删除作用域为scope的fn函数的所有延迟运行、缓冲运行设置,移除监听函数
            }
        }
    },

    //删除当前对象的所有listeners，包括managed listeners
    clearListeners: function () {
        var events = this.events,
            ev,
            key;

        for (key in events) {
            if (!events.hasOwnProperty(key)) {
                continue;
            }
            ev = events[key];
            if (ev.isEvent) {
                ev.clearListeners();
            }
        }

        this.clearManagedListeners();
    },

    purgeListeners: function () {
        console.warn('MixedCollection: purgeListeners has been deprecated. Please use clearListeners.');
        return this.clearListeners.apply(this, arguments);
    },

    //删除当前对象所有的managed listeners
    clearManagedListeners: function () {
        var managedListeners = this.managedListeners || [],
            ln = managedListeners.length,
            i, managedListener;

        for (i = 0; i < ln; i++) {
            managedListener = managedListeners[i];
            managedListener.item.un(managedListener.ename, managedListener.fn, managedListener.scope);
        }

        this.managedListener = [];
    },

    purgeManagedListeners: function () {
        console.warn('MixedCollection: purgeManagedListeners has been deprecated. Please use clearManagedListeners.');
        return this.clearManagedListeners.apply(this, arguments);
    },

    //将指定的事件添加到events列表中，Observable可能会触发它
    //参数可以是一个以事件名作为属性名，以true作为属性值的对象，也可以是多个代表事件名的字符串
    addEvents: function (o) {
        var me = this;
        me.events = me.events || {};//存放 { 事件名：Ext.util.Event对象 }的数值
        if (Ext.isString(o)) {
            var a = arguments,
            i = a.length;
            while (i--) {
                me.events[a[i]] = me.events[a[i]] || true;
            }
        } else {
            Ext.applyIf(me.events, o);
        }
    },

    //查询当前对象是否包含指定的事件帧听器
    hasListener: function (ename) {
        var e = this.events[ename];
        return e.isEvent === true && e.listeners.length > 0;
    },

    //暂停所有事件的触发
    //参数：一个布尔值，设为true时，在resumeEvents被调用后，排列所有被暂停的事件，而不是丢弃它们
    suspendEvents: function (queueSuspended) {
        this.eventsSuspended = true;
        if (queueSuspended && !this.eventQueue) {
            this.eventQueue = [];
        }
    },

    //继续触发事件。
    resumeEvents: function () {
        var me = this,
            queued = me.eventQueue || [];

        me.eventsSuspended = false;
        delete me.eventQueue;

        Ext.each(queued,
        function (e) {
            me.fireEvent.apply(me, e);
        });
    },


    relayEvents: function (origin, events, prefix) {
        prefix = prefix || '';
        var me = this,
            len = events.length,
            i, ename;

        function createHandler(ename) {
            return function () {
                return me.fireEvent.apply(me, [prefix + ename].concat(Array.prototype.slice.call(arguments, 0, -1)));
            };
        }

        for (i = 0, len = events.length; i < len; i++) {
            ename = events[i].substr(prefix.length);
            me.events[ename] = me.events[ename] || true;
            origin.on(ename, createHandler(ename), me);
        }
    },


    enableBubble: function (events) {
        var me = this;
        if (!Ext.isEmpty(events)) {
            events = Ext.isArray(events) ? events : Ext.toArray(arguments);
            Ext.each(events, function (ename) {
                ename = ename.toLowerCase();
                var ce = me.events[ename] || true;
                if (Ext.isBoolean(ce)) {
                    ce = new Ext.util.Event(me, ename);
                    me.events[ename] = ce;
                }
                ce.bubble = true;
            });
        }
    }
});

Ext.override(Ext.util.Observable, {

    on: Ext.util.Observable.prototype.addListener,

    un: Ext.util.Observable.prototype.removeListener,

    mon: Ext.util.Observable.prototype.addManagedListener,
    mun: Ext.util.Observable.prototype.removeManagedListener
});


Ext.util.Observable.releaseCapture = function (o) {
    o.fireEvent = Ext.util.Observable.prototype.fireEvent;
};


Ext.util.Observable.capture = function (o, fn, scope) {
    o.fireEvent = Ext.createInterceptor(o.fireEvent, fn, scope);
};


Ext.util.Observable.observe = function (cls, listeners) {
    if (cls) {
        if (!cls.isObservable) {
            Ext.applyIf(cls, new Ext.util.Observable());
            Ext.util.Observable.capture(cls.prototype, cls.fireEvent, cls);
        }
        if (typeof listeners == 'object') {
            cls.on(listeners);
        }
        return cls;
    }
};


Ext.util.Observable.observeClass = Ext.util.Observable.observe;

